---
title: SAIF.Services.Appworx architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-08-21
library: SAIF.Services.Appworx
reference_type: embedded
---

# SAIF.Services.Appworx architecture

`SAIF.Services.Appworx` is a small, single-purpose integration/service library. Despite the `SAIF.Services.*` naming it is not a hosted service — it is a thin client-side adapter, compiled directly into the LegalMaintenance web application, that translates a "run this batch job" intent into the Appworx enterprise scheduler's Oracle submission contract (the `submit_appworx_job` stored procedure).

## Responsibilities
- Translate a "run this batch job with these arguments" intent into the Appworx scheduler's Oracle submission contract (`submit_appworx_job`), normalizing argument handling (fixed 20 positional slots, empty-slot suppression, defaults for requestor and printer).
- Provide a stateful instance API (`clsRequestAppworxJob`) and a stateless shared convenience overload (`SubmitBatchJob`) that constructs a fresh instance per call.
- Reset argument state between submissions (`InitArgs`) so a reused instance cannot leak arguments from a previous job.
- Optionally redirect submissions to a fixed, hard-coded Appworx-hosting Oracle database/schema (`PRADT` on `WCISPROD`/`WCISDEV1`) instead of the caller's own data portal, via the `inUseWCISDEV1AppworxForAllDevEnv` flag.

## Component boundaries
- `clsRequestAppworxJob` (class, `SAIF.Services.Appworx/clsRequestAppworxJob.vb`) is the sole hand-written type in the library. It has no base class, implements no interfaces, and takes no part in the BOF `OnRetrieve`/`OnSave` business-object lifecycle — it uses the BOF data portal purely as a command channel*.
- Instance API: constructor, `DPI`, `ModuleName`, `Requestor`, `Printer`, `Arg1`–`Arg20` properties, `SubmitBatchJob` (instance), `InitArgs`.
- Shared convenience overload: `SubmitBatchJob` (Shared) — the form actually used by all in-repo callers — which optionally redirects the data portal, constructs the instance, maps only non-`Nothing` arguments, and submits.
- No `IBusinessCriteria` implementations or nested `Criteria` types exist; the library performs no application-layer SQL beyond the single stored-procedure call.
- The library is a leaf/foundation project with no outbound `<ProjectReference>` elements — all collaborators (`IDataPortalInfo`, `clsSmartString`, `clsMSOracleDataLayer`, `AppGlobal`) come from external SAIF framework packages, not from repo projects.

## Interaction model
- **Application/business → scheduler:** application managers in `SAIF.Application.Claim.Legal` (`clsCreateFileManager`, `clsMailDateManager`, `clsRequestManager`) call the shared `SubmitBatchJob` overload; from that point the work is asynchronous and out-of-process — the library returns as soon as the job row is accepted and has no visibility into scheduler execution, success, or output.
- **Library → database:** all traffic goes through the BOF data portal (`IDataPortalInfo.ProcessPortalRequest`) rather than raw ADO.NET, so connection management, credentials, and provider selection are the framework's concern.
- **Deliberate escape hatch:** the shared overload can bypass the caller's data portal entirely and construct its own `clsMSOracleDataLayer("PRADT", "WCISPROD" | "WCISDEV1")`, hard-coding a schema/owner and two database aliases directly into the library rather than relying on configuration.
- **Statefulness:** the instance API is mutable and reusable (`InitArgs` allows resetting between submissions), but the shared overload creates a fresh instance per call, so the class is used statelessly by this repository's code.
- **Error posture:** the only failure handling is a `Try`/`Catch` around `ProcessPortalRequest` that rethrows a wrapped `ApplicationException`; there is no logging, retry, or compensating action inside this library.

## Architecture diagram
The following diagram shows the high-level flow from an application-layer caller through this library to the Appworx scheduler's Oracle stored procedure.

```mermaid
flowchart TD
	A[SAIF.Application.Claim.Legal<br>clsCreateFileManager / clsMailDateManager / clsRequestManager] --> B[clsRequestAppworxJob.SubmitBatchJob<br>Shared overload]
	B --> C[clsRequestAppworxJob<br>instance: ModuleName, Requestor, Printer, Arg1..Arg20]
	C --> D[clsRequestAppworxJob.SubmitBatchJob<br>instance method]
	D --> E[IDataPortalInfo.ProcessPortalRequest<br>BOF data portal]
	E --> F[submit_appworx_job<br>Oracle stored procedure]
	B -.optional redirect.-> G[clsMSOracleDataLayer<br>PRADT / WCISPROD or WCISDEV1]
	G --> E
```

## Sequence diagram
The following diagram shows the primary submission sequence used by all observed in-repo call sites.

```mermaid
sequenceDiagram
	participant Caller as Application manager
	participant Shared as SubmitBatchJob (Shared)
	participant Instance as clsRequestAppworxJob
	participant Portal as IDataPortalInfo
	participant Proc as submit_appworx_job
	Caller->>Shared: SubmitBatchJob(inDPI, inModule, inRequestor, args...)
	Shared->>Instance: New clsRequestAppworxJob(lDPI)
	Instance->>Instance: InitArgs()
	Shared->>Instance: set ModuleName, Requestor, Printer, ArgN (non-Nothing only)
	Shared->>Instance: SubmitBatchJob()
	Instance->>Portal: ProcessPortalRequest(PortalRequest)
	Portal->>Proc: execute submit_appworx_job(inModule, inrequestor, inprinter, inargN...)
	Proc-->>Portal: NonQuery completion (no output)
	Portal-->>Instance: result
	Instance-->>Caller: returns (or rethrows wrapped ApplicationException)
```

## Design constraints
- No validation exists on `ModuleName`, `Requestor`, `Printer`, or argument content within this library; the receiving procedure also performs no validation**.
- Parameter sizes are fixed to the scheduler's contract: module 30, requestor 32, printer 30, each argument 4000 characters.
- The submission is fire-and-forget — `RequestType = DataRequestType.NonQuery`, no output parameters are registered, and the unused `vResult` local is never assigned or read, so callers cannot correlate a submission with a scheduler job instance from this library*.
- Only argument slots explicitly set (non-`Nothing` on the shared overload, non-empty `clsSmartString` on the instance) are transmitted, so positional argument gaps are possible and expected (observed callers skip arg3).
- The differing requestor defaults between the two entry points (`"APPWORX"` on the instance field vs. `"Appworx"` on the shared overload's optional parameter) mean the instance-field default is only observable when the class is constructed directly*.
- No authorization checks are performed by this library; any caller holding a valid `IDataPortalInfo` can submit any Appworx module with any arguments — enforcement is the responsibility of the calling application layer and the database account behind the data portal*.

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [Procedures](procedures/index.md)
- [API reference](api/index.md)

## Sources
- `SAIF.Services.Appworx/SAIF.Services.Appworx.vbproj`
- `SAIF.Services.Appworx/clsRequestAppworxJob.vb`
- `SAIF.Services.Appworx/packages.config`
- `SAIF.Services.Appworx/App.config`
- `SAIF.Services.Appworx/Web.config`
- `SAIF.Business.Claim.Legal/SAIF.Business.Claim.Legal.vbproj`
- `SAIF.Application.Claim.Legal/SAIF.Application.Claim.Legal.vbproj`
- `SAIF.Application.Claim.Legal/LegalNet/clsRequestManager.vb`
- `SAIF.Application.Claim.Legal/LegalNet/clsMailDateManager.vb`
- `SAIF.Application.Claim.Legal/LegalNet/clsCreateFileManager.vb`
